    //生产者(write)
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/shm.h>
    #include <string.h>
    #include <signal.h>
     
    #define MAX 32 
    void *pAddr;
    int shmId;
     
    struct Msg{
      int flag;//0为读,1为写
      long long content[MAX];
    };                          //content：存catalan数   flag：共享内存占用标志的信号
     
    void Handle(int s){
      if(s == 2)
      {
         //本函数调用并不删除所指定的共享内存区，而只是将先前用shmat函数连接（attach）好的共享内存脱离（detach）目前的进程
         shmdt(pAddr);     
         shmctl(shmId,IPC_RMID,0);  //完成对共享内存的控制，删除这片共享内存
         exit(0);
      }
    } 
     
     
     
    int main(){
      int n = 0;    //Catalan数的数目
      int i=0,j=0;
    	
      
      /*
         按ctrl+c键退出时会处理这个消息，进行共享内存卸载、删除操作(handle功能),最后exit(0)退出程序
         signal函数和书上的信号量signal不一样，这里的功能使调用handle函数并把2作为handle的参数
      */
      signal(2,Handle);
     
      /*
        key_t ftok(char *fname,int id)将一个已存在的路径名和一个整数标识符转换成一个key_t值
        得到IPC通信的key，用于创建共享内存。"."表示文件名为当前目录，按照ftok的规则，由于我的read程 
        序也在当前目录，使用的ftok函数的参数相同，因此得到的key也相同
      */
      key_t key = ftok(".",2);
     
      /* 
         创建共享内存，shmId是共享内存标识符
         100表示申请的共享内存是100字节；IPC_CREAT | IPC_EXCL | 0666 :前两个保证创建新内存，否则返            
         回值为-1，0666是3位八进制数，6即二进制110，表示可读可写不可执行，从左到右分别对应当前用户， 
         group组用户，其他用户
      */  
      shmId = shmget(key,100,IPC_CREAT | IPC_EXCL | 0666); 
     
      pAddr = shmat(shmId,0,0);  //把共享内存区对象映射到调用进程的地址空间,随后可像本地地址空间一样进行访问，第二个参数指定为0让内核决定内存的位置，第三个参数0表示可读写
     
      if(*(int *)pAddr == -1){
        printf("shmat error!\n"); 
        exit(0);
      }
     
     
      memset(pAddr,0,100); //将pAddr处的100个字节设置为NULL
      struct Msg *msg = (struct Msg *)pAddr; //msg 指向共享内存
      msg->flag = 1;       //表示写进程占用共享内存
      while(1){
        if(msg->flag == 1){//当为1时写消息,此时读文件中不能操作此共享内存
          i=0;  
          for(i=0;i<MAX;i++)
    	    msg->content[i]=0;    //初始化
     
          printf("The number of catalan:");
          scanf("%d",&n);
          msg->content[0] = 1;
          for(j=1;j<n;j++)
    	    msg->content[j] = msg->content[j-1]*(4*j+2)/(j+2); //计算Catalan数
     
          msg->flag = 0;//当写消息后flag置为0，让读文件开始执行读操作，此时写文件不能进行写操作
        }
        else{
          sleep(1);        //停止1s，让读进程读取msg指向的数据（共享内存）并输出
        }
      }
      return 0;
    }